
#include "StarDictImpl.h"
#include <iostream>
#include <fstream>
#include <iterator>
#include "helper.h"

#ifdef _WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif

using namespace std;

StarDictImpl::StarDictImpl(void): 
index_content_(new char[0]),
dict_entry_(new char[0]),
compressed_dict(false)
{
}

StarDictImpl::~StarDictImpl(void)
{
	delete[] index_content_;
	delete[] dict_entry_;
}

bool StarDictImpl::load_ifo(const std::string& path)
{
	string filename(path+".ifo");
	ifstream in(filename.c_str());
	if(!in.is_open())
	{
		cerr<<"Cannot open the file: "<<filename<<'.'<<endl;
		return false;
	}

	string idx_file_content((istreambuf_iterator<char>(in)), istreambuf_iterator<char>());

	dict_info_.author			= read_field_value(idx_file_content, "author");
	dict_info_.version			= read_field_value(idx_file_content, "version");
	dict_info_.bookname			= read_field_value(idx_file_content, "bookname");
	dict_info_.email			= read_field_value(idx_file_content, "email");
	dict_info_.website			= read_field_value(idx_file_content, "website");
	dict_info_.date				= read_field_value(idx_file_content, "date");
	dict_info_.description		= read_field_value(idx_file_content, "description");
	dict_info_.sametypesequence	= read_field_value(idx_file_content, "sametypesequence");

	dict_info_.word_count		= atoi(read_field_value(idx_file_content, "wordcount").c_str());
	dict_info_.idx_file_size	= atoi(read_field_value(idx_file_content, "idxfilesize").c_str());


	if(dict_info_.version[0] == '2')
		dict_info_.idx_offset_bits = 32;
	else if(dict_info_.version[0] == '3')
		dict_info_.idx_offset_bits = 64;
	else
		return false;

	return true;
}

bool StarDictImpl::load_idx(const std::string& path)
{
	string filename(path+".idx");
	ifstream in(filename.c_str(), ios_base::in | ios_base::binary);
	if(!in.is_open())
	{
		cerr<<"Cannot open the file: "<<filename<<'.'<<endl;
		return false;
	}

	delete[] index_content_;
	index_content_ = new char[dict_info_.idx_file_size];

	in.read(index_content_, dict_info_.idx_file_size);
	if(dict_info_.idx_file_size != in.tellg())
	{
		cerr<<"Cannot properly read the file: "<<path<<'.'<<endl;
		return false;
	}
	word_index_.reserve(dict_info_.word_count);

	char *p = index_content_;

	size_t offset = sizeof(char); //for '\0'
	offset += dict_info_.idx_offset_bits>>3; //for word_data_offset
	offset += sizeof(unsigned int); //for word_data_size

	for (size_t i = 0; i < dict_info_.word_count; ++i)
	{
		word_index_.push_back(p);

		p += strlen(p) + offset;
	}

	return true;
}

bool StarDictImpl::load_dict(const std::string& path)
{
	string filename_uncompressed(path+".dict");
	dict_file_.open(filename_uncompressed.c_str(), ios_base::in | ios_base::binary);
	if(dict_file_.is_open())
	{
		compressed_dict = false;
		return true;
	}
	dict_file_.close();
	dict_file_.clear();

	string filename_compressed(path+".dict.dz");
	dict_file_.open(filename_compressed.c_str(), ios_base::in | ios_base::binary);
	if(dict_file_.is_open())
	{
		compressed_dict = true;
		return true;
	}
	
	cerr<<"Cannot open the files: "<<filename_uncompressed<<" or "<<filename_compressed<<'.'<<endl;

	return false;
}

char* StarDictImpl::get_word(size_t index)
{
	return word_index_[index];
}

char* StarDictImpl::get_entry(size_t index)
{
	char* p = NULL;

	size_t entry_offset = 0;
	size_t entry_size = 0;

	p = word_index_[index];
	p += strlen(p) + sizeof(char);
	entry_offset = ntohl(*reinterpret_cast<const size_t*>(p));
	p += dict_info_.idx_offset_bits>>3;
	entry_size = ntohl(*reinterpret_cast<const size_t*>(p));

	if(!dict_info_.sametypesequence.empty())
	{
		delete[] dict_entry_;
		dict_entry_ = new char[entry_size];


	}
}

//TODO
char* StarDictImpl::get_entry_uncompressed(size_t index)
{
	return NULL;
}

char* StarDictImpl::get_entry_compressed(size_t index)
{
	return NULL;
}
